#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/select.h>
#include <errno.h>
#include <signal.h>
#include "common.h"
#include "server.h"

static void (* set_signal(int signo,void (*func)(int)))(int)
{
	struct sigaction act,oact;
	act.sa_handler=func;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	if(signo != SIGALRM)
		act.sa_flags|=SA_RESTART;
	if(sigaction(signo,&act,&oact)<0)
		return NULL;
	return (oact.sa_handler);
}

static void make_daemon()
{
	pid_t pid;
	if((pid=fork())!=0)
		exit(0);
	setsid();
	set_signal(SIGHUP,SIG_IGN);
	set_signal(SIGCHLD,sig_routine);
	if((pid=fork())!=0)
		exit(0);
	chdir("/");
	umask(0);
}

static void sig_routine()
{
	pid_t chld;
	int   ret;
	while(1)
	{
		chld=wait(&ret);
		if(chld>0) return;
	}
}

int main()
{
	int socketed=-1, binded=-1, listened=-1,accepted=-1,ret=-1;
	struct sockaddr_in  server_addr,client_addr;
	int lenth;
	int opt=1;
	int tmp=-1;
	int i;
	int *p;

	tmp=server_init();
	if(tmp<0)
	{
		printf("error init - ");
		return -1;
	}

	#define MAX setting.connect_max
	
	TIDPOOL tid[MAX];

	thread_pool_init(tid,MAX);
	
	lenth=sizeof(struct sockaddr_in);

	memset(&server_addr,0,sizeof(server_addr));

	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(2005);
	server_addr.sin_addr.s_addr=INADDR_ANY;

	socketed=socket(AF_INET,SOCK_STREAM,0);
	if(socketed<0)
	{
		perror("error socket -\n ");
		return -1;
	}

	if(setsockopt(socketed,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))<0)
	{
		perror("error setsockopt -\n ");
		close(socketed);
		return -1;
	}

	binded=bind(socketed,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in));
	if(binded<0)
	{
		perror("error bind -\n ");
		close(socketed);
		return -1;
	}
	
	//make_daemon();
	
	listened=listen(socketed,10);
	if(listened<0)
	{
		perror("error listen -\n ");
		close(binded);
		close(socketed);
		return -1;
	}

	while(1) 
	{
		accepted=accept(socketed,(struct sockaddr *)&server_addr,&lenth);
		if(accepted<0)
		{
			perror("error accept -\n ");
			close(listened);
			close(binded);
			close(socketed);
			return -1;
		}
		for(i=0;i<MAX;i++)
		{
			if(tid[i].tid==-1)
				break;
		}
		p=malloc(sizeof(int));
		*p = accepted;
		ret=pthread_create(&tid[i].tid,NULL,thread_fun,(void *)p);
		if(ret<0)
		{
			perror("error pthread - \n");
			close(accepted);
			close(listened);
			close(binded);
			close(socketed);
			return -1;
		}
	}
	close(accepted);
	close(listened);
	close(binded);
	close(socketed);
	return 0;
}
